// ApiRequest.ts - RestFull风格的请求工具

// 请求配置接口
export interface ApiRequestConfig extends RequestInit {
  // 基础URL
  baseURL?: string;
  // 查询参数
  params?: Record<string, unknown>;
  // 超时时间（毫秒）
  timeout?: number;
  // 请求前拦截器
  beforeRequest?: (config: ApiRequestConfig) => void | Promise<void>;
  // 响应后拦截器
  afterResponse?: (response: Response, data: unknown) => void | Promise<void>;
  // 错误处理拦截器
  onError?: (error: Error) => void;
  // 是否显示错误提示
  showErrorToast?: boolean;
}

// 响应数据接口
export interface ApiResponse<T = unknown> {
  code: number;
  message: string;
  data: T;
}

// HTTP方法类型
export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';

/**
 * 构建带查询参数的URL
 * @param url 基础URL
 * @param params 查询参数对象
 * @returns 拼接查询参数后的完整URL
 */
const buildUrlWithParams = (url: string, params?: Record<string, unknown>): string => {
  if (!params) return url;

  const searchParams = new URLSearchParams();
  Object.keys(params).forEach(key => {
    if (params![key] !== undefined && params![key] !== null) {
      searchParams.append(key, String(params![key]));
    }
  });

  const queryString = searchParams.toString();
  return queryString ? `${url}${url.includes('?') ? '&' : '?'}${queryString}` : url;
};

/**
 * 添加超时功能的Promise包装
 * @param promise fetch请求Promise
 * @param timeout 超时时间（毫秒）
 * @returns 带超时的Promise
 */
const withTimeout = <T>(promise: Promise<T>, timeout: number): Promise<T> => {
  return new Promise((resolve, reject) => {
    const timer = setTimeout(() => {
      reject(new Error('请求超时'));
    }, timeout);

    promise
      .then(resolve)
      .catch(reject)
      .finally(() => clearTimeout(timer));
  });
};

/**
 * ApiRequest类 - 封装RestFull风格的HTTP请求
 */
class ApiRequest {
  private defaultConfig: ApiRequestConfig;

  constructor(config: ApiRequestConfig = {}) {
    this.defaultConfig = {
      baseURL: process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3001/api',
      timeout: 10000,
      headers: {
        'Content-Type': 'application/json',
      },
      showErrorToast: true,
      ...config
    };
  }

  /**
   * 通用请求方法
   * @param method HTTP方法
   * @param endpoint API端点
   * @param data 请求数据
   * @param config 请求配置
   * @returns Promise<ApiResponse<T>>
   */
  async request<T = unknown>(
    method: HttpMethod,
    endpoint: string,
    data?: unknown,
    config: ApiRequestConfig = {}
  ): Promise<ApiResponse<T>> {
    // 合并配置
    const finalConfig: ApiRequestConfig = {
      ...this.defaultConfig,
      ...config,
      method,
      headers: {
        ...this.defaultConfig.headers,
        ...config.headers
      }
    };

    // 构建完整URL
    const baseURL = finalConfig.baseURL || '';
    const fullUrl = buildUrlWithParams(
      endpoint.startsWith('http') ? endpoint : `${baseURL}${endpoint}`,
      finalConfig.params
    );

    // 处理请求体
    let body: string | FormData | undefined;
    if (data) {
      if (data instanceof FormData) {
        body = data;
        // 对于FormData，删除Content-Type以让浏览器自动设置
        delete finalConfig.headers!['Content-Type'];
      } else {
        body = JSON.stringify(data);
      }
    }

    // 准备fetch配置
    const fetchConfig: RequestInit = {
      method,
      headers: finalConfig.headers,
      body: ['GET', 'HEAD'].includes(method) ? undefined : body,
      ...finalConfig
    };

    // 执行请求前拦截器
    try {
      if (finalConfig.beforeRequest) {
        await finalConfig.beforeRequest(finalConfig);
      }
    } catch (error) {
      console.error('请求前拦截器执行失败:', error);
      throw error;
    }

    try {
      // 发送请求（带超时）
      const response = await withTimeout(
        fetch(fullUrl, fetchConfig),
        finalConfig.timeout || 10000
      );

      // 检查响应状态
      if (!response.ok) {
        throw new Error(`HTTP错误! 状态: ${response.status}`);
      }

      // 解析响应数据
      let responseData: unknown;
      const contentType = response.headers.get('content-type');
      const contentLength = response.headers.get('content-length');
      
      if (contentLength === '0' || !contentType?.includes('application/json')) {
        responseData = { code: 200, message: '成功', data: null };
      } else {
        try {
          responseData = await response.json();
        } catch (jsonError) {
          responseData = { code: 200, message: '成功', data: null };
        }
      }

      // 执行响应后拦截器
      try {
        if (finalConfig.afterResponse) {
          await finalConfig.afterResponse(response, responseData);
        }
      } catch (error) {
        console.error('响应后拦截器执行失败:', error);
      }

      // 检查业务状态码
      if (typeof responseData === 'object' && responseData !== null && 'code' in responseData) {
        const apiResponse = responseData as ApiResponse<T>;
        if (apiResponse.code && apiResponse.code !== 0 && apiResponse.code !== 200) {
          const errorMessage = (apiResponse as unknown as Record<string, unknown>).message?.toString() || '请求失败';
          if (finalConfig.showErrorToast) {
            // 这里可以使用antd的message组件或其他提示组件
            console.error(errorMessage);
          }
          throw new Error(errorMessage);
        }
      }

      return responseData as ApiResponse<T>;
    } catch (error) {
      const errorInstance = error as Error;
      
      // 执行错误处理拦截器
      try {
        if (finalConfig.onError) {
          finalConfig.onError(errorInstance);
        } else if (finalConfig.showErrorToast) {
          console.error(errorInstance.message || '网络请求失败');
        }
      } catch (hookError) {
        console.error('错误处理拦截器执行失败:', hookError);
      }

      throw error;
    }
  }

  /**
   * GET请求
   * @param endpoint API端点
   * @param config 请求配置
   * @returns Promise<ApiResponse<T>>
   */
  get<T = unknown>(endpoint: string, config?: ApiRequestConfig): Promise<ApiResponse<T>> {
    return this.request<T>('GET', endpoint, undefined, config);
  }

  /**
   * POST请求
   * @param endpoint API端点
   * @param data 请求数据
   * @param config 请求配置
   * @returns Promise<ApiResponse<T>>
   */
  post<T = unknown>(endpoint: string, data?: unknown, config?: ApiRequestConfig): Promise<ApiResponse<T>> {
    return this.request<T>('POST', endpoint, data, config);
  }

  /**
   * PUT请求
   * @param endpoint API端点
   * @param data 请求数据
   * @param config 请求配置
   * @returns Promise<ApiResponse<T>>
   */
  put<T = unknown>(endpoint: string, data?: unknown, config?: ApiRequestConfig): Promise<ApiResponse<T>> {
    return this.request<T>('PUT', endpoint, data, config);
  }

  /**
   * DELETE请求
   * @param endpoint API端点
   * @param config 请求配置
   * @returns Promise<ApiResponse<T>>
   */
  delete<T = unknown>(endpoint: string, config?: ApiRequestConfig): Promise<ApiResponse<T>> {
    return this.request<T>('DELETE', endpoint, undefined, config);
  }

  /**
   * PATCH请求
   * @param endpoint API端点
   * @param data 请求数据
   * @param config 请求配置
   * @returns Promise<ApiResponse<T>>
   */
  patch<T = unknown>(endpoint: string, data?: unknown, config?: ApiRequestConfig): Promise<ApiResponse<T>> {
    return this.request<T>('PATCH', endpoint, data, config);
  }
}

// 创建默认实例
const apiRequest = new ApiRequest();

// 导出类和实例
export { ApiRequest };
export default apiRequest;